import { Injectable, EventEmitter } from "@angular/core";
import { Headers, Http } from "@angular/http";
import { CmHttp } from "http-module";
import { Observable } from "rxjs/Observable";
import { UserToken, DEFAULT_VERIFY } from "./user-token";
import { StockPosition } from "./stock-position";
import { StockBusinessHistory } from "./stock-business-history";
import { BASEURL } from "shared";

const TIME_OUT = 80000;

const ENTRUST_BS_SELL = 2;

// 沙盒环境
const HsSandboxUrl = "https://sandbox.hscloud.cn";
// 正式环境
export const HsOpenUrl = "https://vopen.hscloud.cn";

@Injectable()
export class HsClientService {
  timer = Observable.interval(TIME_OUT);
  getTokenSource = this.http.get(
    `${BASEURL}/simtrades/me`, {
      withCredentials: true
    }).publishLast();
  userToken;

  broadcast = new EventEmitter();

  constructor(private http: CmHttp, private ngHttp: Http) {
    this.getTokenSource.connect();
    // 启动时直接获取token
    this.getTokenSource.subscribe(res => {
      this.userToken = res;
      console.debug("Hs Client: ", res);
    }, err => {
      this.userToken = undefined;
      // 继续获取 token 数据
      this.getTokenSource.connect();
      console.error("Hs Client Error: ", err);
    });

    // 每80000毫秒更新Token
    this.timer
      .switchMap(() => this.getTokenSource)
      .subscribe(res => {
        this.userToken = res;
        console.debug("Hs Client: ", res);
      }, err => {
        this.userToken = undefined;
        console.error("Hs Client Error: ", err);
      });
  }

  getBalanceFast(userToken) {
    return this.http.post(
      `${HsOpenUrl}/secu/v1/balancefast_qry`,
      DEFAULT_VERIFY,  // { money_type: 0 },
      {
        headers: new Headers({
          Authorization: `Bearer ${userToken.token}`
        }),
      }).filter(res => res.data)
      .map(body => body["data"]);
  }

  queryBalanceFast() {
    console.debug("Query Balance Fast: ", this.userToken);
    if (!this.userToken) {
      return this.getTokenSource.switchMap(userToken => this.getBalanceFast(userToken));
    }
    return this.getBalanceFast(this.userToken);
  }

  getStockPosition(userToken) {
    return this.http.post(
      `${HsOpenUrl}/secu/v1/stockposition_qry`,
      DEFAULT_VERIFY,
      {
        headers: new Headers({
          Authorization: `Bearer ${userToken.token}`
        }),
      })
      .map(body => {
        if (body["data"]) {
          return body["data"];
        } else {
          return { retry: true };
        }
      });

  }

  queryStockPosition() {
    // console.debug("Query Stock Position: ", this.userToken);
    if (!this.userToken) {
      return this.getTokenSource.switchMap(userToken => this.getStockPosition(userToken));
    }
    return this.getStockPosition(this.userToken);
  }

  getBusiness(userToken) {
    return this.http.post(`${HsOpenUrl}/secu/v1/business_qry`, DEFAULT_VERIFY, {
      // return this.http.post(`${HsOpenUrl}/secu/v1/businesshis_qry`, Object.assign({}, { "start_date": "20161203", "end_date": "20170101" }, DEFAULT_VERIFY), {
      headers: new Headers({
        Authorization: `Bearer ${userToken.token}`
      }),
    }).filter(body => !!body["data"])
      .map(body => body["data"]);
  }

  queryBusiness() {
    // console.debug("Query Entrust: ", this.userToken);
    if (!this.userToken) {
      return this.getTokenSource.switchMap(userToken => this.getBusiness(userToken));
    };
    return this.getBusiness(this.userToken);
  }

  queryEntrust() {
    // console.debug("Query Entrust: ", this.userToken);
    if (!this.userToken) return Observable.empty();
    return this.http.post(`${HsOpenUrl}/secu/v1/entrust_qry`, DEFAULT_VERIFY, {
      headers: new Headers({
        Authorization: `Bearer ${this.userToken.token}`
      }),
    }).filter(body => !!body["data"])
      .map(body => body["data"]);
  }

  queryEntrustHis(date) {
    // console.debug("Query Entrust History: ", date, this.userToken);
    if (!this.userToken) return Observable.empty();
    return this.http.post(`${HsOpenUrl}/secu/v1/entrusthis_qry`, Object.assign({}, { "start_date": date.start, "end_date": date.end }, DEFAULT_VERIFY), {
      headers: new Headers({
        Authorization: `Bearer ${this.userToken.token}`
      }),
    }).filter(body => !!body["data"])
      .map(body => body["data"]);
  }

  queryBusinessHis(date) {
    // console.debug("Query Business History: ", date, this.userToken);
    if (!this.userToken) return Observable.empty();
    return this.http.post(`${HsOpenUrl}/secu/v1/businesshis_qry`, Object.assign({}, { "start_date": date.start, "end_date": date.end }, DEFAULT_VERIFY), {
      headers: new Headers({
        Authorization: `Bearer ${this.userToken.token}`
      }),
    }).filter(body => body && body["data"])
      .map(body => this.businessHisFactory(body["data"]));
  }

  queryAmountSale(data) {
    return this.http.post(`${HsOpenUrl}/secu/v1/stockcode_enter`, Object.assign({}, {
      "exchange_type": data.exchange_type,
      "stock_account": data.stock_account,
      "stock_code": data.stock_code,
      "entrust_prop": data.entrust_prop
    }, DEFAULT_VERIFY), {
        headers: new Headers({
          Authorization: `Bearer ${this.userToken.token}`
        })
      }).filter(body => !!body["data"])
      .map(body => body["data"]);
  }

  queryAmountBuy(data) {
    return this.http.post(`${HsOpenUrl}/secu/v1/almostbuy_qry`, Object.assign({}, {
      "exchange_type": data.exchange_type,
      "stock_account": data.stock_account,
      "stock_code": data.stock_code,
      "entrust_price": data.entrust_price,
      "entrust_prop": data.entrust_prop
    }, DEFAULT_VERIFY), {
        headers: new Headers({
          Authorization: `Bearer ${this.userToken.token}`
        })
      });
    // .filter(body => !!body["data"])
    // .map(body => body["data"]);
  }

  postEntrust(data) {
    console.debug("Post Entrust Sheet: ", data, this.userToken);
    return this.http.post(`${HsOpenUrl}/secu/v1/entrust_enter`,
      Object.assign({}, {
        "exchange_type": data.exchange_type,
        "stock_account": data.stock_account,
        "stock_code": data.stock_code,
        "entrust_amount": data.entrust_amount,
        "entrust_price": data.entrust_price,
        "entrust_bs": data.entrust_bs,
        "entrust_prop": data.entrust_prop  // 0 for 买卖, reference: https://open.hscloud.cn/wiki/doc/dict.html#1200
      }, DEFAULT_VERIFY), {
        headers: new Headers({
          Authorization: `Bearer ${this.userToken.token}`
        }),
      }); //.map(res => res.json());
    // .filter(body => !!body["data"])
    // .map(body => body["data"]);
    // .subscribe(res => console.log('post entrust res:', res),
    // err => console.log('post entrust err:', err));
  }

  businessHisFactory(businesses: StockBusinessHistory[]) {
    return businesses.map(bus =>
      Object.assign({}, bus, {
        commission_charge: this.getCommissionCharge(bus).toFixed(2),
        stamp_tax: this.getStampTax(bus).toFixed(2),
        transfer_fee: this.getTransferFee(bus).toFixed(2),
        other_fee: "-",
        clear_fee: this.getClearFee(bus).toFixed(2)
      })
    );
  }

  getTransferFee(bus: StockBusinessHistory) {
    return +bus.entrust_bs === ENTRUST_BS_SELL ? /60\d{4}$/.test(bus.stock_code) ? Math.max(1, bus.business_balance * 0.01 / 100) : 0 : 0;
  }

  getStampTax(bus: StockBusinessHistory) {
    return +bus.entrust_bs === ENTRUST_BS_SELL ? Math.max(5, bus.business_balance * 0.01 / 100) : 0;
  }

  getCommissionCharge(bus: StockBusinessHistory) {
    return Math.max(5, bus.business_balance * 0.03 / 100);
  }

  getClearFee(bus: StockBusinessHistory) {
    return bus.business_balance - this.getTransferFee(bus) - this.getStampTax(bus) - this.getCommissionCharge(bus);
  }

  withdrawEnter(entrustNo: number) {
    console.debug("Query Stock Position: ", this.userToken);
    if (!this.userToken) {
      return this.getTokenSource.switchMap(userToken => this.withdrawEnterImplement(entrustNo, userToken));
    }
    return this.withdrawEnterImplement(entrustNo, this.userToken);
  }
  withdrawEnterImplement(entrustNo: number, userToken: string) {
    return this.http.post(`${HsOpenUrl}/secu/v1/withdraw_enter`,
      Object.assign({}, {
      }, DEFAULT_VERIFY, {
          entrust_no: entrustNo
        }), {
        headers: new Headers({
          Authorization: `Bearer ${this.userToken.token}`
        }),
        // }, {
        //   isShowFailedModal: true,
        //   isShowSuccessModal: true,
        //   successTips: [
        //     "撤销委托单成功"
        //   ]
      }); // error_code, error_no, error_info
  }
}